import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
import pickle

class VersionedXGBModel:
    __version__ = "1.0.0"

    def load_data(self, filepath):
        # 从Excel文件加载数据
        df = pd.read_excel(filepath)
        X = df.iloc[:, :9]
        y = df.iloc[:, 9]
        return X, y

    def preprocess_data(self, X):
        # 数据预处理，将输入特性标准化
        scaler = StandardScaler()
        X_scaled = scaler.fit_transform(X)
        return X_scaled

    def predict(self, model, X_scaled):
        # 使用已训练的模型进行预测
        pred = model.predict(X_scaled)
        return pred

    def evaluate_model(self, model, X_test_scaled, y_test):
        # 计算模型的评价指标
        y_test_pred = model.predict(X_test_scaled)
        mse_test = mean_squared_error(y_test, y_test_pred)
        rmse_test = np.sqrt(mse_test)
        return rmse_test, y_test_pred

    def plot_comparison(self, y_test, y_test_pred):
        # 绘制实际值与预测值的比较图
        plt.figure(figsize=(14, 6))
        plt.plot(y_test.values, label='Actual Values', linestyle='-', linewidth=2)
        plt.plot(y_test_pred, label='Predicted Values', linestyle='--', linewidth=2)
        plt.title('Comparison of Actual and Predicted Values')
        plt.xlabel('Observation Number')
        plt.ylabel('Target Value')
        plt.legend()
        plt.show()

    def plot_error(self, y_test, y_test_pred):
        # 绘制误差图
        errors = y_test.values - y_test_pred
        plt.figure(figsize=(14, 6))
        plt.scatter(y_test.values, errors, alpha=0.5)
        plt.title('Error Plot')
        plt.xlabel('Actual Values')
        plt.ylabel('Predicted Error')
        plt.axhline(0, color='red', linestyle='--')
        plt.show()

if __name__ == '__main__':
    # 载入已训练的模型
    with open('trained_model.pkl', 'rb') as handle:
        trained_model = pickle.load(handle)

    model = VersionedXGBModel()
    # 加载并预处理验证集数据
    X, y = model.load_data('test_set.xlsx')
    X_val = model.preprocess_data(X)

    # 用已训练的模型进行预测和评价
    rmse_test, y_test_pred = model.evaluate_model(trained_model, X_val, y)
    print(f'测试集的均方根误差: {rmse_test}')

    # 绘制图像
    model.plot_comparison(y, y_test_pred)
    model.plot_error(y, y_test_pred)